package com.galaxy.payment.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.galaxy.common.core.utils.MapstructUtils;
import com.galaxy.common.core.utils.StringUtils;
import com.galaxy.common.mybatis.core.page.PageQuery;
import com.galaxy.common.mybatis.core.page.TableDataInfo;
import com.galaxy.payment.domain.PaymentRecord;
import com.galaxy.payment.domain.bo.PaymentBo;
import com.galaxy.payment.domain.convert.PaymentRecordConvert;
import com.galaxy.payment.domain.vo.PaymentRecordVo;
import com.galaxy.payment.mapper.PaymentRecordMapper;
import com.galaxy.payment.service.IPaymentRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 支付记录Service业务层处理
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class PaymentRecordServiceImpl implements IPaymentRecordService {

    private final PaymentRecordMapper baseMapper;

    @Override
    public PaymentRecord queryById(Long id) {
        return baseMapper.selectById(id);
    }

    @DS("slave")
    @Override
    public TableDataInfo<PaymentRecordVo> queryPageList(PaymentBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PaymentRecord> lqw = buildQueryWrapper(bo);
        IPage<PaymentRecordVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
        for(PaymentRecordVo paymentRecordVo : page.getRecords()){
            // 假设 paymentRecordVo.getCreateTime() 返回 Date 类型
            updateStatus(paymentRecordVo);
        }
        return TableDataInfo.build(page);
    }

    @DS("master")
    private void updateStatus(PaymentRecordVo paymentRecordVo) {
        Date createTime = paymentRecordVo.getCreateTime();
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.MINUTE, -15);
        Date fifteenMinutesAgo = calendar.getTime();
        if(paymentRecordVo.getPaymentType() != null && (paymentRecordVo.getStatus() == 0
            || paymentRecordVo.getStatus() == 1) && createTime.after(fifteenMinutesAgo)){
            baseMapper.update(new LambdaUpdateWrapper<PaymentRecord>()
                .set(PaymentRecord::getStatus, 3)
                .eq(PaymentRecord::getId, paymentRecordVo.getId()));
        }
    }

    @DS("slave")
    @Override
    public List<PaymentRecordVo> queryList(PaymentBo bo) {
        LambdaQueryWrapper<PaymentRecord> lqw = buildQueryWrapper(bo);
        List<PaymentRecordVo> paymentRecordVos = baseMapper.selectVoList(lqw);
        for(PaymentRecordVo paymentRecordVo : paymentRecordVos){
            // 假设 paymentRecordVo.getCreateTime() 返回 Date 类型
            updateStatus(paymentRecordVo);
        }
        return paymentRecordVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentBo insertByBo(PaymentBo bo) {
        PaymentRecord add = PaymentRecordConvert.INSTANCE.boToEntity(bo);
        validEntityBeforeSave(add);
        add.setPayTime(new Date());
        bo.setPayNo(generatePayNo());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return bo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(PaymentBo bo) {
        PaymentRecord update = PaymentRecordConvert.INSTANCE.boToEntity(bo);
//        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatusByPayNo(PaymentBo bo) {
        PaymentRecord update = baseMapper.selectOne(Wrappers.<PaymentRecord>lambdaQuery()
            .eq(PaymentRecord::getPayNo, bo.getPayNo()));
        if (update == null) {
            log.info("没有该支付记录！！！{}", bo.getPayNo());
            return false;
        }
        update.setStatus(bo.getStatus());
        return baseMapper.updateById(update) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO: 做一些业务上的校验,判断是否允许删除
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean handlePaymentCallback(String payNo, String tradeNo, Integer status) {
        PaymentRecord paymentRecord = baseMapper.selectOne(Wrappers.<PaymentRecord>lambdaQuery()
            .eq(PaymentRecord::getPayNo, payNo));
        if (paymentRecord == null) {
            log.info("没有该支付记录！！！{}", payNo);
            return false;
        }
        paymentRecord.setTradeNo(tradeNo);
        paymentRecord.setStatus(status);
        if (status == 2) { // 支付成功
            paymentRecord.setSuccessTime(new Date());
        }
        return baseMapper.updateById(paymentRecord) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelPayment(String payNo) {
        PaymentRecord paymentRecord = baseMapper.selectOne(Wrappers.<PaymentRecord>lambdaQuery()
            .eq(PaymentRecord::getPayNo, payNo));
        if (paymentRecord == null) {
            log.info("没有该支付记录！！！{}", payNo);
            return false;
        }
        if (paymentRecord.getStatus() != 0) {
            log.info("该支付记录状态不是待支付，无法取消！！！{}", payNo);
            return false;
        }
        if (paymentRecord.getExpireTime() != null && paymentRecord.getExpireTime().before(new Date())) {
            log.info("该支付记录已过期，无法取消！！！{}", payNo);
            return false;
        }
        paymentRecord.setStatus(3); // 设置为失败状态
        return baseMapper.updateById(paymentRecord) > 0;
    }

    @Override
    public PaymentRecordVo createPayment(PaymentBo bo) {
        // 生成支付单号
        bo.setPayNo(generatePayNo());
        // 设置初始状态为待支付
        bo.setStatus(0);
        // 设置过期时间（30分钟后）
        bo.setExpireTime(new Date(System.currentTimeMillis() + 30 * 60 * 1000));
        // 保存支付记录
        PaymentBo success = insertByBo(bo);
        if (success.getId() == null) {
            throw new RuntimeException("创建支付记录失败");
        }
        // 获取并返回支付记录
        PaymentRecordVo paymentRecordVo = new PaymentRecordVo();
        paymentRecordVo.setPayNo(success.getPayNo());
        paymentRecordVo.setPaymentAmount(success.getPaymentAmount());
        paymentRecordVo.setPaymentType(success.getPaymentType());
        paymentRecordVo.setStatus(success.getStatus());
        paymentRecordVo.setSuccessTime(success.getSuccessTime());
        paymentRecordVo.setExpireTime(success.getExpireTime());
        paymentRecordVo.setUserId(success.getUserId());
        paymentRecordVo.setOrderId(success.getOrderId());
        paymentRecordVo.setOrderNo(success.getOrderNo());
        paymentRecordVo.setPayTime(success.getPayTime());
        paymentRecordVo.setTradeNo(success.getTradeNo());
        paymentRecordVo.setUpdateTime(success.getUpdateTime());
        paymentRecordVo.setCreateTime(success.getCreateTime());
        paymentRecordVo.setId(success.getId());
        paymentRecordVo.setSearchValue(success.getSearchValue());
        paymentRecordVo.setCreateBy(success.getCreateBy());
        paymentRecordVo.setUpdateBy(success.getUpdateBy());
        paymentRecordVo.setCreateDept(success.getCreateDept());
        paymentRecordVo.setParams(success.getParams());
        return paymentRecordVo;
    }

    @Override
    public PaymentRecordVo getPaymentRecord(String payNo) {
        PaymentRecord record = baseMapper.selectOne(Wrappers.<PaymentRecord>lambdaQuery()
            .eq(PaymentRecord::getPayNo, payNo));
        if (record == null) {
            return null;
        }
        return PaymentRecordConvert.INSTANCE.entityToVo(record);
    }

    @Override
    public PaymentRecordVo getPaymentRecordByOrderNo(String orderNo) {
        PaymentRecord record = baseMapper.selectOne(new LambdaQueryWrapper<PaymentRecord>()
            .eq(PaymentRecord::getOrderNo, orderNo)
            .last("limit 1"));
        if (record == null) {
            return null;
        }
        return PaymentRecordConvert.INSTANCE.entityToVo(record);
    }

    @Override
    public PaymentRecordVo getPaymentRecordById(Long id) {
        PaymentRecord record = baseMapper.selectById(id);
        if (record == null) {
            return null;
        }
        return PaymentRecordConvert.INSTANCE.entityToVo(record);
    }

    /**
     * 生成支付单号
     */
    private String generatePayNo() {
        return "PAY" + System.currentTimeMillis() + String.format("%04d", (int)(Math.random() * 10000));
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<PaymentRecord> buildQueryWrapper(PaymentBo bo) {
        LambdaQueryWrapper<PaymentRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, PaymentRecord::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getPayNo()), PaymentRecord::getPayNo, bo.getPayNo());
        lqw.eq(bo.getPaymentType() != null, PaymentRecord::getPaymentType, bo.getPaymentType());
        lqw.eq(bo.getStatus() != null, PaymentRecord::getStatus, bo.getStatus());
        lqw.orderByDesc(PaymentRecord::getCreateTime);
        return lqw;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PaymentRecord entity) {
        if (entity.getPaymentAmount() == null || entity.getPaymentAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("支付金额必须大于0");
        }
        if (entity.getPaymentType() == null) {
            throw new IllegalArgumentException("支付方式不能为空");
        }
        if (entity.getUserId() == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (StringUtils.isBlank(entity.getOrderNo())) {
            throw new IllegalArgumentException("订单编号不能为空");
        }
    }
}
